//定义状态变量 方便统一控制
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

function resolvePromise(p, x, resolve, reject) {
	if (x === p) {
		throw new TypeError('返回值错误')
	}
	if (x instanceof myPromise) {
		x.then(
			res => {
				console.log('res==', res)
				resolve(res)
			},
			err => {
				console.log('err==', err)
				reject(err)
			}
		)
	} else {
		resolve(x)
	}
}

// 定义一个异步方法
function runAsyncToask(callBack) {
	if (typeof queueMicrotask === 'function') {
		queueMicrotask(callBack)
	} else if (typeof MutationObserver === 'function') {
		const obs = new MutationObserver(callBack)
		const nodeDiv = document.createElement('div')
		obs.observe(nodeDiv, { childList: true })
		nodeDiv.innerText = '冲刺'
	} else {
		setTimeout(callBack, 0)
	}
}

class myPromise {
	// 定义promise的状态和原因
	state = PENDING
	result = undefined

	// 定义一个私有属性 记录异步操作的回调函数
	#handler = [] //格式：[{onFulfilled,onRejected},{onFulfilled,onRejected}]

	//定义构造函数
	// 1. 定义resolve/reject 
	// 1.1 改变状态(不可逆)
	// 1.2.记录原因
	// 2.执行回调函数
	constructor(func) {
		// 定义resolve/reject  改变状态 && 记录原因
		const resolve = (result) => {
			if (this.state === PENDING) {
				this.state = FULFILLED
				this.result = result
				this.#handler.forEach(v => {
					v.onFulfilled(this.result)
				})
			}
			return result
		}

		const reject = (result) => {
			if (this.state === PENDING) {
				this.state = REJECTED
				this.result = result
				this.#handler.forEach(v => {
					v.onRejected(this.result)
				})
			}
			return result
		}

		// 执行回调函数
		try {
			func(resolve, reject)
		} catch (error) {
			reject(error)
		}
	}


	//定义then方法
	// 1.添加实例方法then，并设置成功回调onFulfilled、失败回调onRejected
	// 2.执行成功回调
	// 3.执行失败回调
	then(onFulfilled, onRejected) {
		// 如果onFulfilled/onRejected 不是一个函数,把他替换为函数
		onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (x) => { x }
		onRejected = typeof onRejected === 'function' ? onRejected : (x) => { throw x }

		const p = new myPromise((resolve, reject) => {
			if (this.state === FULFILLED) {
				runAsyncToask(() => {
					try {
						const x = onFulfilled(this.result)
						resolvePromise(p, x, resolve, reject)
					} catch (error) {
						reject(error)
					}
				})
			} else if (this.state === REJECTED) {
				runAsyncToask(() => {
					try {
						const x = onRejected(this.result)
						resolvePromise(p, x, resolve(), reject())
					} catch (error) {
						reject(error)
					}
				})
			} else if (this.state === PENDING) {
				//this.state === PENDING 表示异步操作，因为只有异步操作，有延迟改变state的效果
				this.#handler.push({
					onFulfilled: () => {
						runAsyncToask(() => {
							try {
								const x = onFulfilled(this.result)
								resolvePromise(p, x, resolve, reject)
							} catch (error) {
								reject(error)
							}
						})
					},
					onRejected: () => {
						runAsyncToask(() => {
							try {
								const x = onRejected(this.result)
								resolvePromise(p, x, resolve, reject)
							} catch (error) {
								reject(error)
							}
						})
					}
				})
			}
		})

		return p
	}

	catch (onRejected) {
		return this.then(undefined, onRejected)
	}
}

export default myPromise